package v1beta1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.
const (
	GuestReasonWaitForVpc   = "waitForVpc"
	GuestReasonCreateFailed = "createFailed"
	GuestReasonStopFailed   = "stopFailed"
)

// GuestSpec defines the desired state of Guest
type GuestSpec struct {
	OwnerId   string `json:"ownerId,omitempty"`
	ProjectId string `json:"projectId,omitempty"`
	// provider secret
	ProviderRef   ProviderRef `json:"providerRef,omitempty"`
	ImageRef      string      `json:"imageRef,omitempty"`
	FlavorRef     string      `json:"flavorRef,omitempty"`
	VPCRef        string      `json:"vpcRef,omitempty"`
	DataVolumeRef string      `json:"dataVolumeRef,omitempty"`
	//+optional
	DataVolumeRefs []string `json:"dataVolumeRefs,omitempty"`
	Name           string   `json:"name,omitempty"`
	//+optional
	Password string `json:"password,omitempty"`
	Nodename string `json:"nodeName,omitempty"`
	Vcpu     int32  `json:"vcpu,omitempty"`
	//+optional
	CpuArch string `json:"cpuArch,omitempty"`
	Vmemory int64  `json:"vmemory,omitempty"`
	//+optional
	GpuType string `json:"gpuType,omitempty"`
	//+optional
	Vgpu     int32  `json:"vgpu,omitempty"`
	UserData string `json:"userData,omitempty"`
	Hostname string `json:"hostName,omitempty"`
	// DesireStae defines what State desired of the instances. support: Running,Stopped,Rebooted.
	// Running desires the instance should be running in the end.
	// Stopped desires the instance should be stopped in the end.
	// Rebooted state is an progress of guest. first call reboot than change state to Running.
	//+kubebuilder:default:=Running
	DesireState GuestPhaseType `json:"desireState,omitempty"`
	// eg. rendering,creation
	// createion: 制作模型的虚拟机,从vsphere中选举
	JobType          string           `json:"jobType,omitempty"`
	ResourceAffinity ResourceAffinity `json:"resourceAffinity,omitempty"`
	//+optional
	Probe Probe `json:"probe,omitempty"`
	//+optional
	FileVolumeNames []string `json:"fileVolumeNames,omitempty"`
	// +optional
	OrderInfo OrderInfo `json:"orderInfo,omitempty"`
}

type Probe struct {
	//+optional
	//+kubebuilder:default:=600
	TimeoutSeconds int32 `json:"timeoutSeconds,omitempty" protobuf:"varint,3,opt,name=timeoutSeconds"`
	// Minimum consecutive failures for the probe to be considered failed after having succeeded.
	// Defaults to 3. Minimum value is 1.
	// +optional
	ProbeTimestamp metav1.Time `json:"probeTimestamp,omitempty" protobuf:"varint,6,opt,name=failureThreshold"`
}

type VPCInfo struct {
	VPCID    string `json:"vpcid,omitempty"`
	SubnetID string `json:"subnetid,omitempty"`
}

type ResourceAffinity struct {
	CloudResourceId string `json:"cloudResourceId,omitempty"`
	HostName        string `json:"hostName,omitempty"`
	SkuId           string `json:"skuId,omitempty"`
	VMId            string `json:"vmId,omitempty"`
	//+optional
	ResourceIDs map[string]string `json:"resourceIDs"`
	//+optional
	ScheduledResouces map[string]string `json:"scheduledResource,omitempty"`
}

type OrderInfo struct {
	BillingType      string `json:"billingType,omitempty"`
	BillingUnit      string `json:"billingUnit,omitempty"`
	BillingQuantity  int32  `json:"billingQuantity,omitempty"`
	BillingAutoRenew bool   `json:"billingAutoRenew,omitempty"`
	//+optional
	OrderId string `json:"orderId,omitempty"`
	//+optional
	SubOrderId string `json:"subOrderId,omitempty"`
	//+optional
	SubOrderType string `json:"subOrderType"`
	//+optional
	DueTime metav1.Time `json:"dueTime,omitempty"`
	//+optional
	StartTime metav1.Time `json:"startTime,omitempty"`
	//+optional
	FailTimes int32 `json:"failTimes,omitempty"`
	//+optional
	IsBilling bool `json:"isBilling,omitempty"`
}

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true
// +kubebuilder:resource:shortName=guest
// +kubebuilder:subresource:status

// Guest is the Schema for the guest API
type Guest struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec GuestSpec `json:"spec,omitempty"`
	// status of guest
	Status GuestStatus `json:"status,omitempty"`
}

type GuestStatus struct {
	Conditions    []DiskConditions `json:"conditions,omitempty"`
	Phase         GuestPhaseType   `json:"phase,omitempty"`
	Info          GuestInfo        `json:"info,omitempty" protobuf:"bytes,5,opt,name=info"`
	VPC           VPCInfo          `json:"vpc,omitempty"`
	FileVolumeIDs []string         `json:"fileVolumeIDs,omitempty"`
	Message       string           `json:"message,omitempty"`
	//+optional
	DataVolumes DataVolumesInfo `json:"dataVolumes,omitempty"`
	// +optional
	GuestConditions []Condition `json:"guest_conditions,omitempty"`
}
type DataVolumesInfo struct {
	//是否无数据卷
	NoVolumes   bool     `json:"HasVolumes,omitempty"`
	DataVolumes []string `json:"dataVolumes,omitempty"`
}
type GuestConditions struct {
	// Type of deployment condition.
	Type string `json:"type" protobuf:"bytes,1,opt,name=type,casttype=InstallationConditionType"`
	// The last time this condition was updated.
	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty" protobuf:"bytes,6,opt,name=lastUpdateTime"`
	// The reason for the condition's last transition.
	Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
	// A human readable message indicating details about the transition.
	Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
}

// job information of creating disk
type GuestInfo struct {
	Servers []Server `json:"servers,omitempty"`
	JobID   string   `json:"jobid,omitempty"`
}

// TODO sync ip information
type Server struct {
	ID         string `json:"id,omitempty"`
	InternalIP string `json:"internalIP,omitempty"`
	PublicIP   string `json:"publicIP,omitempty"`
	//+optional
	ObtainTime metav1.Time `json:"obtainTime,omitempty"`
	Dnats      []DnatPorts `json:"dnats,omitempty"`
	//+optional
	OsLoginName string `json:"osLoginName,omitempty"`
}

type DnatPorts struct {
	InternalPort int32 ` json:"internalPort,omitempty"`
	ExternalPort int32 `json:"externalPort,omitempty"`
}

type GuestConditionType string
type GuestPhaseType string

const (
	GuestRequestStatus GuestConditionType = "Requested"
	GuestReadyStatus   GuestConditionType = "Ready"
)

const (
	GuestCreatingPhase   GuestPhaseType = "Creating"
	GuestReadyPhase      GuestPhaseType = "Ready"
	GuestStoppedPhase    GuestPhaseType = "Stopped"
	GuestPendingPhase    GuestPhaseType = "Pending"
	GuestRebootPhase     GuestPhaseType = "Rebooted"
	GuestRunningPhase    GuestPhaseType = "Running"
	GuestFailedPhase     GuestPhaseType = "Failed"
	GuestInadequatePhase GuestPhaseType = "Inadequate"
	GuestStoppingPhase   GuestPhaseType = "Stopping"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// GuestList contains a list of Guest item
type GuestList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Guest `json:"items"`
}

func (gs *GuestStatus) ServerIDs() *[]string {
	serverids := []string{}
	for _, s := range gs.Info.Servers {
		serverids = append(serverids, s.ID)
	}
	return &serverids
}
